package main.java.com.curefun.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Scanner;

public class ShellHelper {

    static Logger logger = LoggerFactory.getLogger(ShellHelper.class );


    public static void main(String[] args) {
        System.out.println("input shell:");
        Scanner scan = new Scanner(System.in);
        // 从键盘接收数据
        // 判断是否还有输入
        String commandStr = "";
        if (scan.hasNextLine()) {
            commandStr = scan.nextLine();
            System.out.println("输入的数据为：" + commandStr);
        }
        scan.close();

        ShellHelper.exeShell(commandStr);

    }


    /**
     * 执行shell命令
     * 返回Map包含：
     * status: 1是成功  0是失败，根据process.waitFor()判断命令是否正常执行
     * error:异常信息
     *
     * @param cmd
     */
    public static HashMap<String,String>  exeShell(String cmd)
    {


        StringBuffer sbError = new StringBuffer();
        String status = "1";
        String[] cmds = { "/bin/sh", "-c", cmd };
        Process process;
        try {
            process = Runtime.getRuntime().exec(cmds);
            // 分配处理流，防止阻塞
            dealStream(process);
            int exitValue = process.waitFor();
            if (0 != exitValue) {
                sbError.append("call shell failed. error code is :" + exitValue + ",shell is:" + cmd);
                status = "0";
            }
        }
        catch (Exception e)
        {
            status = "0";
            sbError.append("Exception:" + e.getMessage() + ",shell is:" + cmd);
            e.printStackTrace();
        }
        finally {
            HashMap<String,String> hashMap = new HashMap<String,String>();
            hashMap.put("status",status);
            hashMap.put("error",sbError.toString());
            return  hashMap;
        }
    }


    /**
     * 处理process输出流和错误流，防止进程阻塞
     * 在process.waitFor();前调用
     * 调用ffmpeg命令，可能造成阻塞，解决方法如下：在waitFor()之前，利用单独两个线程，分别处理process的getInputStream()和getErrorSteam()，防止缓冲区被撑满，导致阻塞；
     * 参考：https://www.cnblogs.com/163yun/p/9878915.html
     * @param process
     */
    private static void dealStream(final Process process) {
        if (process == null) {
            return;
        }
        // 处理InputStream的线程
        new Thread() {
            @Override
            public void run() {
                BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line = null;
                try {
                    while ((line = in.readLine()) != null) {
                        logger.info("output: " + line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        // 处理ErrorStream的线程
        new Thread() {
            @Override
            public void run() {
                BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String line = null;
                try {
                    while ((line = err.readLine()) != null) {
                        logger.info("error: " + line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        err.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }



}




